package com.ylyq.ylxx.quarz;

import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.ylyq.ylxx.constants.AccountConstant;
import com.ylyq.ylxx.context.FilterContextHandler;
import com.ylyq.ylxx.entity.YlyqQuartz;
import com.ylyq.ylxx.model.ResponseData;
import com.ylyq.ylxx.model.bean.*;
import com.ylyq.ylxx.model.request.*;
import com.ylyq.ylxx.service.*;
import com.ylyq.ylxx.util.RedisUtil;
import com.ylyq.ylxx.util.Tools;
import io.swagger.annotations.ApiModelProperty;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.quartz.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.quartz.QuartzJobBean;
import org.springframework.stereotype.Component;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @ClassName UploadTask
 * @Description TODO
 * @Author xiaweichao
 * @Date 2020/7/3 11:55
 * @Version 1.0
 */
@Slf4j
@Component
@DisallowConcurrentExecution
public class AutoOpenOrCloseTask extends QuartzJobBean {
    @Autowired
    private IOceanegineReportService iOceanegineReportService;
    @Autowired
    private IOceaneginePlanService iOceaneginePlanService;
    @Autowired
    private IYlyqQuartzService iYlyqQuartzService;
    @Autowired
    private RedisUtil redisUtils;
    @Autowired
    private IOauthService iOauthService;
    @Autowired
    private IOceanegineService iOceanegineService;

    @Override
    protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        //在线程里保存所用的access_token。如果refresh_token 过期了就无法进行启停监控了
        String userId = (String) jobExecutionContext.getTrigger().getJobDataMap().get("userID");
        Long advertiserId = (Long) jobExecutionContext.getTrigger().getJobDataMap().get("advertiserId");
        if (StringUtils.isBlank(userId))
            return;
        String access_token = (String) redisUtils.get("access_token" + userId);
        if (StringUtils.isBlank(access_token)) {
            String refresh_token = (String) redisUtils.get("refresh_token" + userId);
            if (StringUtils.isBlank(refresh_token)) {
                log.error("refresh_token 过期：{}", refresh_token);
                return;
            }
            String accessToken = iOauthService.reFreshAccessToken(userId, refresh_token);
            FilterContextHandler.setOceaneToken(accessToken);
        } else {
            FilterContextHandler.setOceaneToken(access_token);
        }

        log.info(new Date() + "quartz任务开始------------------------------------");
        JobKey key = jobExecutionContext.getJobDetail().getKey();
        log.info("My Job name and group are:" + key.getName() + ":" + key.getGroup());
        TriggerKey trkey = jobExecutionContext.getTrigger().getKey();
        log.info("My Trigger name and group are:" + trkey.getName() + ":" + trkey.getGroup());
//        JobDataMap dataMap = jobExecutionContext.getJobDetail().getJobDataMap();
//        JobDataMap tdataMap = jobExecutionContext.getTrigger().getJobDataMap();
        QueryWrapper<YlyqQuartz> wrapper = new QueryWrapper<>();
        wrapper.eq("job_group", key.getGroup());
        wrapper.eq("job_name", key.getName());
        wrapper.eq("trigger_group", trkey.getGroup());
        wrapper.eq("tirgger_name", trkey.getName());
        wrapper.eq("advertiser_id", advertiserId);
        List<YlyqQuartz> ylyqQuartzList = iYlyqQuartzService.list(wrapper);

        if (ylyqQuartzList == null || ylyqQuartzList.isEmpty())
            return;

//        Set<String> collect = ylyqQuartzList.stream().map(YlyqQuartz::getPlans).collect(Collectors.toSet());
//        Set<Long> planIds = new HashSet<>();
//        for (String temp : collect) {
//            planIds.addAll(Arrays.asList(Tools.StringArray2LongArray(temp.split(","))));
//        }

        Long[] planIds = Tools.StringArray2LongArray(ylyqQuartzList.get(0).getPlans().split(","));//一组自动规则中，里面的计划都是同一组的计划

        //获取计划数据
        GetPlanInfoRequest getPlanInfoRequest = new GetPlanInfoRequest();
        getPlanInfoRequest.setAdvertiser_id(advertiserId);
        getPlanInfoRequest.setPage_size(planIds.length);
        GetPlanInfoRequest.FilteringGetPlanInfoRequest filteringGetPlanInfoRequest = new GetPlanInfoRequest.FilteringGetPlanInfoRequest();
        filteringGetPlanInfoRequest.setIds(planIds);
        getPlanInfoRequest.setFiltering(filteringGetPlanInfoRequest);
        OceanenginePlanInfo planInfo = iOceaneginePlanService.getPlan(getPlanInfoRequest);
        Map<Long, List<OceanenginePlanInfo.DataBean.ListBean>> planCollect = null;
        if (planInfo.getCode() == AccountConstant.SUCCESS) {
            if (null != planInfo.getData().getList() && !planInfo.getData().getList().isEmpty()) {
                List<OceanenginePlanInfo.DataBean.ListBean> planList = planInfo.getData().getList();
                planCollect = planList.stream().collect(Collectors.groupingBy(OceanenginePlanInfo.DataBean.ListBean::getId));
            }
        }

        //获取计划报表数据
        GetReportPlanRequest reportPlanRequest = new GetReportPlanRequest();
        reportPlanRequest.setAdvertiser_id(advertiserId);
//        reportPlanRequest.setStart_date("2020-09-27");//表示获取所有的数据。
        reportPlanRequest.setStart_date(Tools.getDatelaterDay(Tools.getCurrentDate("yyyy-MM-dd"),30));//表示获取所有的数据。
        reportPlanRequest.setEnd_date(Tools.getCurrentDate("yyyy-MM-dd"));
        //暂时按广告计划id过滤
        GetReportPlanRequest.FilteringGetReportPlanRequest filtering = new GetReportPlanRequest.FilteringGetReportPlanRequest();
//        filtering.setAd_ids(planIds.toArray(new Long[planIds.size()]));
        filtering.setAd_ids(planIds);
        reportPlanRequest.setFiltering(filtering);
        reportPlanRequest.setGroup_by(new String[]{"STAT_GROUP_BY_FIELD_ID", "STAT_GROUP_BY_FIELD_STAT_TIME"});
        OceanengineReportPlanInfo oceanengineAccount = iOceanegineReportService.getReportPlan(reportPlanRequest);

        if (oceanengineAccount.getCode() == AccountConstant.SUCCESS) {
            if (null == oceanengineAccount.getData().getList() || oceanengineAccount.getData().getList().isEmpty())
                return;

            List<OceanengineReportPlanInfo.DataBean.ListBean> planReportListTotal = oceanengineAccount.getData().getList();
            Map<Long, List<OceanengineReportPlanInfo.DataBean.ListBean>> reportPlanCollect = planReportListTotal.stream().collect(Collectors.groupingBy(OceanengineReportPlanInfo.DataBean.ListBean::getAd_id));
            for (Map.Entry<Long, List<OceanengineReportPlanInfo.DataBean.ListBean>> reportPlan : reportPlanCollect.entrySet()) {
                Long planId = reportPlan.getKey();
                List<OceanengineReportPlanInfo.DataBean.ListBean> planReportList = reportPlan.getValue();
                //按时间重排序,今天的排在第一，最开始时间排在最后
                Collections.sort(planReportList, new Comparator<OceanengineReportPlanInfo.DataBean.ListBean>() {
                    DateFormat f = new SimpleDateFormat("yyyy-MM-dd");

                    @SneakyThrows
                    @Override
                    public int compare(OceanengineReportPlanInfo.DataBean.ListBean o1, OceanengineReportPlanInfo.DataBean.ListBean o2) {
                        return f.parse(o2.getStat_datetime()).compareTo(f.parse(o1.getStat_datetime()));
                    }
                });

                for (YlyqQuartz ylyqQuartz : ylyqQuartzList) {
                    boolean isMeetCondition = false;//是否满足预设条件
                    int size = ylyqQuartz.getDayNum() == 0 ? planReportList.size() : ylyqQuartz.getDayNum();//统计数据时间。0累计，1当天，7一周，自定义多少天值就多少
                    double convert_cost = 0;
                    long convert = 0;
                    double convert_rate = 0;
                    double cost = 0;
                    double show = 0;
                    long click = 0;
                    double ctr = 0;
                    double avg_click_cost = 0;
                    Double startNum = ylyqQuartz.getStartNum();//比较条件的开始数据
                    Double endNum = ylyqQuartz.getEndNum();//比较条件的结束数据
                    Double rate = ylyqQuartz.getRate();//比较条件的结束数据
                    switch (ylyqQuartz.getDataType()) {//数据类型。1转化成本,2转化数,3转化率,4消耗,5展示数,6点击数,7点击率,8平均点击单价
                        case 1:
                            for (int i = 0; i < size; i++) {
                                convert_cost += planReportList.get(i).getConvert_cost();
                            }
                            switch (ylyqQuartz.getCompareCondition()) {//比较的条件。LESS小于等于，MORE大于等于，INTERVAL介于区间，,LESSBID低于出价，MOREBID高于出价
                                case "LESS":
                                    isMeetCondition = (convert_cost < startNum);
                                    break;
                                case "MORE":
                                    isMeetCondition = (convert_cost > startNum);
                                    break;
                                case "INTERVAL":
                                    isMeetCondition = (convert_cost > startNum && convert_cost < endNum);
                                    break;
                                case "LESSBID":
                                    isMeetCondition = convert_cost < (planCollect.get(planId).get(0).getCpa_bid() * rate);
                                    break;
                                case "MOREBID":
                                    isMeetCondition = convert_cost > (planCollect.get(planId).get(0).getCpa_bid() * rate);
                                    break;
                            }
                            break;
                        case 2:
                            for (int i = 0; i < size; i++) {
                                convert += planReportList.get(i).getConvert();
                            }
                            switch (ylyqQuartz.getCompareCondition()) {//比较的条件。LESS小于等于，MORE大于等于，INTERVAL介于区间
                                case "LESS":
                                    isMeetCondition = (convert < startNum);
                                    break;
                                case "MORE":
                                    isMeetCondition = (convert > startNum);
                                    break;
                                case "INTERVAL":
                                    isMeetCondition = (convert > startNum && convert < endNum);
                                    break;
                            }
                            break;
                        case 3:
                            for (int i = 0; i < size; i++) {
                                convert_rate += planReportList.get(i).getConvert_rate();
                            }
                            convert_rate = convert_rate / size;
                            switch (ylyqQuartz.getCompareCondition()) {//比较的条件。LESS小于等于，MORE大于等于，INTERVAL介于区间
                                case "LESS":
                                    isMeetCondition = (convert_rate < startNum);
                                    break;
                                case "MORE":
                                    isMeetCondition = (convert_rate > startNum);
                                    break;
                                case "INTERVAL":
                                    isMeetCondition = (convert_rate > startNum && convert_rate < endNum);
                                    break;
                            }
                            break;
                        case 4:
                            for (int i = 0; i < size; i++) {
                                cost += planReportList.get(i).getCost();
                            }

                            Integer costCompartType = ylyqQuartz.getCostCompartType();
                            switch (costCompartType) {//当条件为消耗时，比较类型。0金额，1日预算
                                case 0:
                                    switch (ylyqQuartz.getCompareCondition()) {//比较的条件。LESS小于等于，MORE大于等于，INTERVAL介于区间
                                        case "LESS":
                                            isMeetCondition = (cost < startNum);
                                            break;
                                        case "MORE":
                                            isMeetCondition = (cost > startNum);
                                            break;
                                        case "INTERVAL":
                                            isMeetCondition = (cost > startNum && cost < endNum);
                                            break;
                                    }
                                    break;
                                case 1:
                                    GetAccount accountDay = iOceanegineService.getAccountDay(new GetAccountDayRequest(new Long[]{advertiserId}));
                                    if (accountDay.getCode() == AccountConstant.SUCCESS) {
                                        if (null != accountDay.getData() && null != accountDay.getData().getList() && !accountDay.getData().getList().isEmpty())
                                            switch (ylyqQuartz.getCompareCondition()) {//比较的条件。LESS小于等于，MORE大于等于，INTERVAL介于区间
                                                case "LESS":
                                                    isMeetCondition = (cost < accountDay.getData().getList().get(0).getBudget() * startNum);
                                                    break;
                                                case "MORE":
                                                    isMeetCondition = (cost > accountDay.getData().getList().get(0).getBudget() * startNum);
                                                    break;
                                                case "INTERVAL":
                                                    isMeetCondition = (cost > accountDay.getData().getList().get(0).getBudget() * startNum && cost < accountDay.getData().getList().get(0).getBudget() * endNum);
                                                    break;
                                            }
                                    }
                                    break;
                            }
                            break;
                        case 5:
                            for (int i = 0; i < size; i++) {
                                show += planReportList.get(i).getShow();
                            }
                            switch (ylyqQuartz.getCompareCondition()) {//比较的条件。LESS小于等于，MORE大于等于，INTERVAL介于区间
                                case "LESS":
                                    isMeetCondition = (show < startNum);
                                    break;
                                case "MORE":
                                    isMeetCondition = (show > startNum);
                                    break;
                                case "INTERVAL":
                                    isMeetCondition = (show > startNum && show < endNum);
                                    break;
                            }
                            break;
                        case 6:
                            for (int i = 0; i < size; i++) {
                                click += planReportList.get(i).getClick();
                            }
                            switch (ylyqQuartz.getCompareCondition()) {//比较的条件。LESS小于等于，MORE大于等于，INTERVAL介于区间
                                case "LESS":
                                    isMeetCondition = (click < startNum);
                                    break;
                                case "MORE":
                                    isMeetCondition = (click > startNum);
                                    break;
                                case "INTERVAL":
                                    isMeetCondition = (click > startNum && click < endNum);
                                    break;
                            }
                            break;
                        case 7:
                            for (int i = 0; i < size; i++) {
                                ctr += planReportList.get(i).getCtr();
                            }
                            ctr = ctr / size;
                            switch (ylyqQuartz.getCompareCondition()) {//比较的条件。LESS小于等于，MORE大于等于，INTERVAL介于区间
                                case "LESS":
                                    isMeetCondition = (ctr < startNum);
                                    break;
                                case "MORE":
                                    isMeetCondition = (ctr > startNum);
                                    break;
                                case "INTERVAL":
                                    isMeetCondition = (ctr > startNum && ctr < endNum);
                                    break;
                            }
                            break;
                        case 8:
                            for (int i = 0; i < size; i++) {
                                avg_click_cost += planReportList.get(i).getAvg_click_cost();
                            }
                            avg_click_cost = avg_click_cost / size;
                            switch (ylyqQuartz.getCompareCondition()) {//比较的条件。LESS小于等于，MORE大于等于，INTERVAL介于区间
                                case "LESS":
                                    isMeetCondition = (avg_click_cost < startNum);
                                    break;
                                case "MORE":
                                    isMeetCondition = (avg_click_cost > startNum);
                                    break;
                                case "INTERVAL":
                                    isMeetCondition = (avg_click_cost > startNum && avg_click_cost < endNum);
                                    break;
                            }
                            break;
                    }

                    if (isMeetCondition) {
                        log.info("quartz符合条件，开始执行------------------------------------"+ylyqQuartz.toString());
                        Double money = ylyqQuartz.getMoney();//金额值，state为changeBid、upBid、lowBid、changeBudget，upBudget，lowBudget时必填
                        switch (ylyqQuartz.getOperating()) {//执行的操作, enable表示启用, delete表示删除, disable表示暂停，changeBid表示调价至多少，upBid表示提高价格至多少，lowBid表示降低价格至多少，
                            // changeBudget表示调整预算到多少，upBudget表示提高预算到多少,lowBudget表示降低预算到多少
                            case "enable":
                            case "delete":
                            case "disable":
                                OceanengineUpdatePlanStateResult oceanengineUpdatePlanStateResult = iOceaneginePlanService.updateBatchPlanState(new UpdatePlanStateInfoRequest(advertiserId, new Long[]{planId}, ylyqQuartz.getOperating()));
                                if (oceanengineUpdatePlanStateResult.getCode() == AccountConstant.SUCCESS) {
                                    log.info("quartz任务====计划id为：\n" + planId + "updateBatchPlanState success");
                                } else {
                                    log.error("quartz任务====计划id为：\n" + planId + "updateBatchPlanState fail");
                                }

                                break;
                            case "changeBid":
                                List<UpdatePlanBidInfoRequest.DataBean> bidListChange = new ArrayList<>();
                                bidListChange.add(new UpdatePlanBidInfoRequest.DataBean(planId, money));
                                OceanengineUpdatePlanBidResult oceanengineUpdatePlanBidResultChange = iOceaneginePlanService.updateBatchPlanBid(new UpdatePlanBidInfoRequest(advertiserId, bidListChange));
                                if (oceanengineUpdatePlanBidResultChange.getCode() == AccountConstant.SUCCESS) {
                                    log.info("quartz任务====计划id为：\n" + planId + "updateBatchPlanBudget success");
                                } else {
                                    log.error("quartz任务====计划id为：\n" + planId + "updateBatchPlanBudget fail");
                                }
                                break;
                            case "upBid":
                                List<UpdatePlanBidInfoRequest.DataBean> bidListUp = new ArrayList<>();
                                if (planCollect != null && planCollect.get(planId) != null && !planCollect.get(planId).isEmpty())
                                    bidListUp.add(new UpdatePlanBidInfoRequest.DataBean(planId, planCollect.get(planId).get(0).getCpa_bid() + money));
                                OceanengineUpdatePlanBidResult oceanengineUpdatePlanBidResult = iOceaneginePlanService.updateBatchPlanBid(new UpdatePlanBidInfoRequest(advertiserId, bidListUp));
                                if (oceanengineUpdatePlanBidResult.getCode() == AccountConstant.SUCCESS) {
                                    log.info("quartz任务====计划id为：\n" + planId + "updateBatchPlanBudget success");
                                } else {
                                    log.error("quartz任务====计划id为：\n" + planId + "updateBatchPlanBudget fail");
                                }
                                break;
                            case "lowBid":
                                List<UpdatePlanBidInfoRequest.DataBean> bidListLow = new ArrayList<>();
                                if (planCollect != null && planCollect.get(planId) != null && !planCollect.get(planId).isEmpty())
                                    bidListLow.add(new UpdatePlanBidInfoRequest.DataBean(planId, planCollect.get(planId).get(0).getCpa_bid() - money));
                                OceanengineUpdatePlanBidResult oceanengineUpdatePlanBidResultLow = iOceaneginePlanService.updateBatchPlanBid(new UpdatePlanBidInfoRequest(advertiserId, bidListLow));
                                if (oceanengineUpdatePlanBidResultLow.getCode() == AccountConstant.SUCCESS) {
                                    log.info("quartz任务====计划id为：\n" + planId + "updateBatchPlanBudget success");
                                } else {
                                    log.error("quartz任务====计划id为：\n" + planId + "updateBatchPlanBudget fail");
                                }
                                break;

                            case "changeBudget":
                                List<UpdatePlanBudgetInfoRequest.DataBean> budgetListChange = new ArrayList<>();
                                budgetListChange.add(new UpdatePlanBudgetInfoRequest.DataBean(planId, money));
                                OceanengineUpdatePlanBudgetResult oceanengineUpdatePlanBudgetResultChange = iOceaneginePlanService.updateBatchPlanBudget(new UpdatePlanBudgetInfoRequest(advertiserId, budgetListChange));
                                if (oceanengineUpdatePlanBudgetResultChange.getCode() == AccountConstant.SUCCESS) {
                                    log.info("quartz任务====计划id为：\n" + planId + "updateBatchPlanBudget success");
                                } else {
                                    log.error("quartz任务====计划id为：\n" + planId + "updateBatchPlanBudget fail");
                                }
                                break;
                            case "upBudget":
                                List<UpdatePlanBudgetInfoRequest.DataBean> budgetListUp = new ArrayList<>();
                                if (planCollect != null && planCollect.get(planId) != null && !planCollect.get(planId).isEmpty())
                                    budgetListUp.add(new UpdatePlanBudgetInfoRequest.DataBean(planId, planCollect.get(planId).get(0).getBudget() + money));
                                OceanengineUpdatePlanBudgetResult oceanengineUpdatePlanBudgetResultUp = iOceaneginePlanService.updateBatchPlanBudget(new UpdatePlanBudgetInfoRequest(advertiserId, budgetListUp));
                                if (oceanengineUpdatePlanBudgetResultUp.getCode() == AccountConstant.SUCCESS) {
                                    log.info("quartz任务====计划id为：\n" + planId + "updateBatchPlanBudget success");
                                } else {
                                    log.error("quartz任务====计划id为：\n" + planId + "updateBatchPlanBudget fail");
                                }
                                break;
                            case "lowBudget":
                                List<UpdatePlanBudgetInfoRequest.DataBean> budgetListLow = new ArrayList<>();
                                if (planCollect != null && planCollect.get(planId) != null && !planCollect.get(planId).isEmpty())
                                    budgetListLow.add(new UpdatePlanBudgetInfoRequest.DataBean(planId, planCollect.get(planId).get(0).getBudget() - money));
                                OceanengineUpdatePlanBudgetResult oceanengineUpdatePlanBudgetResultLow = iOceaneginePlanService.updateBatchPlanBudget(new UpdatePlanBudgetInfoRequest(advertiserId, budgetListLow));
                                if (oceanengineUpdatePlanBudgetResultLow.getCode() == AccountConstant.SUCCESS) {
                                    log.info("quartz任务====计划id为：\n" + planId + "updateBatchPlanBudget success");
                                } else {
                                    log.error("quartz任务====计划id为：\n" + planId + "updateBatchPlanBudget fail");
                                }
                                break;
                        }
                    }
                }
            }
        }

        log.info(new Date() + "任务结束------------------------------------");
    }
}
